package com.ruoyi.health.dify;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.BufferedSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class DifyClient {

    @Value("${dify.base-url:http://192.168.0.139/v1}")
    private String baseUrl;



    @Value("${dify.token:app-h6Wm7SEXbINMcpgaNXntZIdn}")
    private String bearerToken;

    @Value("${dify.workflow-id:e672a5bb-b280-42e1-86b6-796ae2a4d613}")
    private String defaultWorkflowId;

    @Value("${dify.user:764953119@.com}")
    private String defaultUser;

    @Value("${dify.response-mode:blocking}")
    private String defaultResponseMode;
    // 添加超时配置属性
    @Value("${dify.connect-timeout:10}")
    private int connectTimeout;

    @Value("${dify.read-timeout:1800}")
    private int readTimeout; // 30分钟 = 1800秒
    @Value("${dify.call-timeout:1800}")
    private int callTimeout; // 30分钟 = 1800秒

    @Value("${dify.write-timeout:60}")
    private int writeTimeout;




    private OkHttpClient httpClient;


    @PostConstruct
    public void init() {
        this.httpClient = new OkHttpClient.Builder()
                .connectTimeout(connectTimeout, TimeUnit.SECONDS)     // 连接超时
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)        // 写入超时
                .readTimeout(readTimeout, TimeUnit.SECONDS)   // 读取超时
                .callTimeout(callTimeout, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
                .retryOnConnectionFailure(true)
                .build();
    }

    /**
     * 运行工作流 -
     *

     * @return 响应结果
     */
    public WorkflowResponse runWorkflow(String data,String reportType) {
        Map<String, Object> param = new HashMap<>();
        param.put("healthData", data);
        param.put("reportType", reportType);
        return runWorkflow(param, "/workflows/run");
    }

    public void stopRunWorkflow(String workRunId) {
        String responseJson = executePost(baseUrl, "/workflows/tasks/"+workRunId+"/stop", buildWorkflowRequest(null));
        JSONObject jsonObject = JSONObject.parseObject(responseJson);
        if (jsonObject.getString("result").equals("success")) {
            log.info("任务停止成功");
        } else {
            log.error("任务停止失败");
            throw new RuntimeException("任务停止失败");
        }
    }

    /**
     * 运行工作流 -
     *
     * @return 响应结果
     */
    public void runWorkflow4Stream( Long customerId,String data) {

        Map<String, Object> param = new HashMap<>();
        runWorkflowStream(customerId, param, "/workflows/run");
    }

    /**
     * 运行工作流 -
     *
     * @param fileUrl 文件URL
     * @param taskId  任务id
     * @return 响应结果
     */
    public WorkflowResponse runChatflow(String prefix, String fileUrl, String taskId, String name, String datasets) {

        Map<String, Object> inputs = buildFileInputs(null + fileUrl, taskId, name, datasets);
        return runWorkflow(inputs, "/chat-messages");
    }

    /**
     * 运行工作流 - 通用版本（自定义inputs参数）
     *
     * @param inputs 输入参数
     * @return 响应结果
     */
    public WorkflowResponse runWorkflow(Map<String, Object> inputs, String requestedUrl) {
        Map<String, Object> request = buildWorkflowRequest(inputs);
        String responseJson = executePost(baseUrl, requestedUrl, request);
        return JSONObject.parseObject(responseJson, WorkflowResponse.class);
    }

    public WorkflowStatusResponse getWorkflowStatus(String workRunId) {
        // 构造请求
        String responseJson = executeGet(baseUrl, "/workflows/run/"+workRunId, null);

        return JSONObject.parseObject(responseJson, WorkflowStatusResponse.class);
    }

    /**
     * 运行工作流 - 通用版本（自定义inputs参数）
     *
     * @param inputs 输入参数
     * @return 响应结果
     */
    public void runWorkflowStream(Long policyId, Map<String, Object> inputs, String requestedUrl) {
        Map<String, Object> request = buildWorkflowRequest(inputs);
        executeStream(policyId, baseUrl, requestedUrl, request);
    }



    /**
     * 构建包含文件的工作流输入参数
     *
     * @param fileUrl 文件URL
     * @param taskId  任务id
     * @return inputs参数
     */
    public Map<String, Object> buildFileInputs(String fileUrl, String taskId, String name, String datasets) {
        Map<String, Object> inputs = new HashMap<>();
        // 构建enterFile对象
        Map<String, Object> enterFile = new HashMap<>();
        enterFile.put("transfer_method", "remote_url");
        enterFile.put("url", fileUrl);
        enterFile.put("type", getFileType(fileUrl));

        inputs.put("myfile", enterFile);
        inputs.put("taskid", taskId);
       // inputs.put("name", name);
        inputs.put("datasets", datasets);

        return inputs;
    }

    /**
     * 构建完整的工作流请求参数
     *
     * @param inputs 输入参数
     * @return 完整请求参数
     */
    public Map<String, Object> buildWorkflowRequest(Map<String, Object> inputs) {
        Map<String, Object> request = new HashMap<>();
        request.put("workflow_id", defaultWorkflowId);
        request.put("user", defaultUser);
        request.put("response_mode", defaultResponseMode);
        request.put("inputs", inputs != null ? inputs : new HashMap<>());
        return request;
    }



    /**
     * 执行POST请求
     *
     * @param path        请求路径
     * @param requestBody 请求体
     * @return 响应结果
     */
    private String executePost(String prefix, String path, Map<String, Object> requestBody) {

        try {
            String url = prefix + (prefix.endsWith("/") ? path.substring(1) : path);

            // 构造请求体
            String jsonBody = JSONObject.toJSONString(requestBody);
            RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"), jsonBody);

            // 构造请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("Authorization", "Bearer " + bearerToken)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Accept", "application/json")
                    .build();

            // 执行请求
            try (Response response = httpClient.newCall(request).execute()) {
                if (response.isSuccessful() && response.body() != null) {
                    String responseBody = response.body().string();
                    log.info("Dify请求成功，URL: {}，响应: {}", url, responseBody);
                    return responseBody;
                } else {
                    String errorMsg = "Dify请求失败，URL: " + url + "，状态码: " + response.code();
                    if (response.body() != null) {
                        errorMsg += "，响应: " + response.body().string();
                    }
                    log.error(errorMsg);
                    throw new RuntimeException(errorMsg);
                }
            }
        } catch (Exception e) {
            log.error("Dify请求异常，路径: {}", path, e);
            throw new RuntimeException("Dify请求异常: " + e.getMessage(), e);
        }
    } /**
     * 执行POST请求
     *
     * @param path        请求路径
     * @param jsonBody 请求体
     * @return 响应结果
     */
    private String executePost2(String prefix, String path, String jsonBody) {

        try {
            String url = prefix + (prefix.endsWith("/") ? path.substring(1) : path);

            // 构造请求体
            RequestBody body = RequestBody.create(MediaType.get("text/plain; charset=utf-8"), jsonBody);

            // 构造请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();

            // 执行请求
            try (Response response = httpClient.newCall(request).execute()) {
                if (response.isSuccessful() && response.body() != null) {
                    String responseBody = response.body().string();
                    log.info("Dify请求成功，URL: {}，响应: {}", url, responseBody);
                    return responseBody;
                } else {
                    String errorMsg = "Dify请求失败，URL: " + url + "，状态码: " + response.code();
                    if (response.body() != null) {
                        errorMsg += "，响应: " + response.body().string();
                    }
                    log.error(errorMsg);
                    throw new RuntimeException(errorMsg);
                }
            }
        } catch (Exception e) {
            log.error("Dify请求异常，路径: {}", path, e);
            throw new RuntimeException("Dify请求异常: " + e.getMessage(), e);
        }
    }

    /**
     * 执行GET请求
     *
     * @param prefix 请求基础URL
     * @param path   请求路径
     * @param params 请求参数
     * @return 响应结果
     */
    private String executeGet(String prefix, String path, Map<String, Object> params) {
        try {
            // 构建完整的URL
            String url = prefix + (prefix.endsWith("/") ? path.substring(1) : path);

            // 添加查询参数
            if (params != null && !params.isEmpty()) {
                StringBuilder urlBuilder = new StringBuilder(url);
                urlBuilder.append("?");

                boolean first = true;
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    if (!first) {
                        urlBuilder.append("&");
                    }
                    urlBuilder.append(entry.getKey())
                            .append("=")
                            .append(entry.getValue());
                    first = false;
                }
                url = urlBuilder.toString();
            }

            // 构造请求
            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .addHeader("Authorization", "Bearer " + bearerToken)
                    .addHeader("Accept", "application/json")
                    .build();

            // 执行请求
            try (Response response = httpClient.newCall(request).execute()) {
                if (response.isSuccessful() && response.body() != null) {
                    String responseBody = response.body().string();
                    log.info("Dify GET请求成功，URL: {}，响应: {}", url, responseBody);
                    return responseBody;
                } else {
                    String errorMsg = "Dify GET请求失败，URL: " + url + "，状态码: " + response.code();
                    if (response.body() != null) {
                        errorMsg += "，响应: " + response.body().string();
                    }
                    log.error(errorMsg);
                    throw new RuntimeException(errorMsg);
                }
            }
        } catch (Exception e) {
            log.error("Dify GET请求异常，路径: {}", path, e);
            throw new RuntimeException("Dify GET请求异常: " + e.getMessage(), e);
        }
    }


    /**
     * 执行POST请求
     *
     * @param path        请求路径
     * @param requestBody 请求体
     * @return 响应结果
     */
    private void executeStream(Long policyId, String prefix, String path, Map<String, Object> requestBody) {
        try {
            String url = prefix + (prefix.endsWith("/") ? path.substring(1) : path);

            // 构造请求体
            String jsonBody = JSONObject.toJSONString(requestBody);
            RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"), jsonBody);

            // 构造请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("Authorization", "Bearer " + bearerToken)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Accept", "application/json")
                    .build();

            // 执行请求
            Call call = httpClient.newCall(request);
            try (Response response = call.execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }

                if (response.body() == null) {
                    throw new IOException("Response body is null");
                }

                // 获取响应流
                BufferedSource source = response.body().source();
                // 逐行读取
                while (!source.exhausted()) {
                    String line = source.readUtf8Line();
                    if (line == null) break;

                    line = line.trim();
                    if (line.isEmpty()) continue;

                    // 处理 SSE 事件
                    if (line.startsWith("data:")) {

                        String jsonStr = line.substring(5).trim();
                        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                        String workflowRunId = jsonObject.getString("workflow_run_id");
                        String event = jsonObject.getString("event");

                        if ("workflow_started".equals(event)) {
                            log.info("Dify SSE事件: " + line);

                        } else if ("workflow_finished".equals(event)) {
                            log.info("Dify SSE事件: " + line);
                            String status = jsonObject.getJSONObject("data").getString("status");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("Dify请求异常，路径: {}", path, e);
        }
    }

    /**
     * 根据文件URL获取文件类型
     *
     * @param fileUrl 文件URL
     * @return 文件类型 (document/image/audio/video/custom)
     */
    private String getFileType(String fileUrl) {
        if (fileUrl == null || fileUrl.isEmpty()) {
            return "document";
        }

        String lowerUrl = fileUrl.toLowerCase();

        // 文档类型
        if (lowerUrl.endsWith(".txt") || lowerUrl.endsWith(".md") || lowerUrl.endsWith(".markdown") ||
                lowerUrl.endsWith(".pdf") || lowerUrl.endsWith(".html") || lowerUrl.endsWith(".htm") ||
                lowerUrl.endsWith(".xlsx") || lowerUrl.endsWith(".xls") || lowerUrl.endsWith(".docx") ||
                lowerUrl.endsWith(".doc") || lowerUrl.endsWith(".csv") || lowerUrl.endsWith(".eml") ||
                lowerUrl.endsWith(".msg") || lowerUrl.endsWith(".pptx") || lowerUrl.endsWith(".ppt") ||
                lowerUrl.endsWith(".xml") || lowerUrl.endsWith(".epub")) {
            return "document";
        }

        // 图片类型
        if (lowerUrl.endsWith(".jpg") || lowerUrl.endsWith(".jpeg") || lowerUrl.endsWith(".png") ||
                lowerUrl.endsWith(".gif") || lowerUrl.endsWith(".webp") || lowerUrl.endsWith(".svg")) {
            return "image";
        }

        // 音频类型
        if (lowerUrl.endsWith(".mp3") || lowerUrl.endsWith(".m4a") || lowerUrl.endsWith(".wav") ||
                lowerUrl.endsWith(".webm") || lowerUrl.endsWith(".amr")) {
            return "audio";
        }

        // 视频类型
        if (lowerUrl.endsWith(".mp4") || lowerUrl.endsWith(".mov") || lowerUrl.endsWith(".mpeg") ||
                lowerUrl.endsWith(".mpga")) {
            return "video";
        }

        // 默认返回custom类型
        return "custom";
    }


    // Getters for external access if needed
    public String getDefaultWorkflowId() {
        return defaultWorkflowId;
    }

    public String getDefaultUser() {
        return defaultUser;
    }

    public String getDefaultResponseMode() {
        return defaultResponseMode;
    }
}
